package com.ship.dispatch.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ship.common.business.service.impl.BaseServiceImpl;
import com.ship.common.core.base.Page;
import com.ship.common.core.domain.R;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.dispatch.bean.SpFile;
import com.ship.dispatch.bean.SpOverhaul;
import com.ship.dispatch.bean.fob.SpFobFileRecord;
import com.ship.dispatch.bean.orderPay.ConFiles;
import com.ship.dispatch.bo.SpOverhaulBO;
import com.ship.dispatch.bpm.service.ProcessInstanceService;
import com.ship.dispatch.mapper.SpOverhaulServiceMapper;
import com.ship.dispatch.service.ConFilesService;
import com.ship.dispatch.service.SpOverhaulService;
import com.ship.dispatch.service.fob.SpFobFileRecordService;
import com.ship.dispatch.vo.SpOverhaulVo;
import com.ship.system.api.BpmInstanceService;
import com.ship.system.api.RemoteFileService;
import com.ship.system.api.domain.SysFile;
import liquibase.pro.packaged.M;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;

import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class SpOverhaulServiceImpl extends BaseServiceImpl<SpOverhaulServiceMapper, SpOverhaul> implements SpOverhaulService {
    @Autowired
    SpOverhaulServiceMapper spOverhaulServiceMapper;

    @Autowired
    SpFobFileRecordService spFobFileRecordService;

    @Value("${file_server.host}")
    private String fileServerHost;

    @Autowired
    private RemoteFileService remoteFileService;

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public JsonResult<SpOverhaul> schemeAdd(SpOverhaul spOverhaul) {
        // 将JSON格式的字符串设置到SpOverhaul对象的fileUrl字段中
//        List<String> fileList = spOverhaul.getFile();
//        JSONArray jsonArray = new JSONArray(fileList);
//        String fileUrl = jsonArray.toString();
//        spOverhaul.setFileUrl(fileUrl);

        String imo = spOverhaulServiceMapper.getImoByName(spOverhaul.getNameOfVessel());
        spOverhaul.setImo(imo);
        spOverhaul.setDelApply(0);
        super.save(spOverhaul);

        Long id = Long.valueOf(spOverhaul.getId());

        SpFobFileRecord spFobFileRecord = new SpFobFileRecord();
        spFobFileRecord.setOverhaulId(id);

//        for (String url : fileList) {
//            SpFile spFile = new SpFile();
//            spFile.setConId(id);
//            spFile.setFileType(3);
//
//            int lastIndex = url.lastIndexOf("/");
//            String fileName = url.substring(lastIndex + 1);
//            int dotIndex = fileName.lastIndexOf(".");
//            String fileNameWithoutExtension = fileName.substring(0, dotIndex);
//
//            spFile.setFileName(fileNameWithoutExtension);
//            spFile.setUrl(url);
//            spFile.setId(generateSerialVersionUID());
//            spOverhaulServiceMapper.saveFile(spFile);
//        }
        for (String fileId : spOverhaul.getFileIds()) {
            spFobFileRecord.setId(Long.valueOf(fileId));
            spFobFileRecordService.updateById(spFobFileRecord);
//            ConFiles conFiles = new ConFiles();
//            conFiles.setUrl(url);
//            conFiles.setConId(id);
//            conFiles.setFileType(3);
//            conFiles.setFileName(fileNameWithout);
//            conFilesService.save(conFiles);
        }

        return JsonResult.success(spOverhaul);
    }

    @Override
    public JsonResult getListInfo(SpOverhaulBO spOverhaulBO) {
        List<SpOverhaul> result;
        Page<SpOverhaul> resultPage = new Page<>();;
        if (!isEmptyList(spOverhaulBO.getImo()) || !isEmptyList(spOverhaulBO.getNameOfVessel())) {
            QueryWrapper<SpOverhaul> queryWrapper = new QueryWrapper<>();
            if (!isEmptyList(spOverhaulBO.getImo())) {
                spOverhaulBO.getImo().forEach(imo ->
                        queryWrapper.or().like("imo", "%" + imo + "%")
                );
            }
            if (!isEmptyList(spOverhaulBO.getNameOfVessel())) {
                spOverhaulBO.getNameOfVessel().forEach(vesselName ->
                        queryWrapper.or().like("name_of_vessel", "%" + vesselName + "%")
                );
            }
            queryWrapper.eq("del_apply", 0).orderByDesc("create_date");

            PageHelper.startPage(spOverhaulBO.getPageNum(), spOverhaulBO.getPageSize());
            result = spOverhaulServiceMapper.selectList(queryWrapper);
        } else {
            PageHelper.startPage(spOverhaulBO.getPageNum(), spOverhaulBO.getPageSize());
            result = spOverhaulServiceMapper.getInfo();
        }
        int totalItems = result.size();
        resultPage.setList(result);
        resultPage.setPageNum(spOverhaulBO.getPageNum());
        resultPage.setPageSize(spOverhaulBO.getPageSize());
        resultPage.setTotal(totalItems);
        return JsonResult.success(resultPage);
    }

    @Override
    public JsonResult<Object> getshipList() {
        List<String> list = spOverhaulServiceMapper.getShipList()
                .stream()
                .distinct()
                .filter(ship -> !ship.startsWith("虚拟船"))
                .collect(Collectors.toList());
        return JsonResult.success(list);
    }

    @Autowired
    @Lazy
    ProcessInstanceService processInstanceService;
    @Override
    public void delApply(Long id) {
        SpOverhaul spOverhaul = super.getById(id);
        if (spOverhaul == null) {
            throw new BusException("删除申请失败!该记录不存在", BaseResultCode.GENERAL_ERROR);
        }
        spOverhaul.setDelApply(1);
        //开启审批流程
        Map<String,Object> map = new HashMap<>();
        map.put("serviceType",1);
        map.put("module","spOverhaul");
        map.put("moduleName","船舶检修");
        String processInstanceId = processInstanceService.createProcessInstance2(BpmInstanceService.SYSTEM_DELETE_BPM_KEY,map,id+"");
        spOverhaul.setProcessInstanceId(processInstanceId);
        super.updateById(spOverhaul);
    }

    @Override
    public String export(SpOverhaulVo spOverhaulVo) throws IOException {
        List<String> ids = spOverhaulVo.getIds();
        List<SpOverhaul> spOverhaulVos;
        if (ids == null || ids.isEmpty()) {
            spOverhaulVos = spOverhaulServiceMapper.getInfo();
        } else {
            spOverhaulVos = spOverhaulServiceMapper.getInFOById(ids);
        }
        Date currentTime = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        String dateString = dateFormat.format(currentTime);
        String folderName = "船舶检修-" + dateString;
        String zipFileName = folderName + ".zip";

        try (FileOutputStream fos = new FileOutputStream(zipFileName);
             ZipOutputStream zos = new ZipOutputStream(fos)) {
            if (spOverhaulVo.getType()) {
                // 创建目录
                File folder = new File(folderName);
                if (!folder.exists()) {
                    folder.mkdirs();
                }
                for (SpOverhaul spOverhaul : spOverhaulVos) {
                    String nameOfVessel = spOverhaul.getNameOfVessel();
                    JSONArray jsonArray = new JSONArray(spOverhaulServiceMapper.getFileById(spOverhaul.getId()));
                    String fileUrl = jsonArray.toString();
                    if (fileUrl != null && !fileUrl.isEmpty() && !fileUrl.equals("[]")) {
                        fileUrl = fileUrl.replaceAll("\\[|\\]", "");
                        String[] urls = fileUrl.split(",");
                        for (String url : urls) {
                            url = url.trim().replaceAll("^\"|\"$", "");
                            if (!url.matches("^\\w+://.*$")) {
                                url = "http://" + url;
                            }
                            downloadFile(url, folderName + "/" + nameOfVessel);
                        }
                    }
                }
                exportToExcel(spOverhaulVos, folderName + "/" + folderName + ".xlsx");
                zipDirectory(new File(folderName), zos, folderName + "/");
            } else {
                exportToExcel(spOverhaulVos, folderName + ".xlsx");
                zipFileName = folderName + ".xlsx";
//                zipFile(folderName + ".xlsx");
            }

        }
        //文件地址
        File file = new File(zipFileName);
//        //声明参数集合
//        HashMap<String, Object> paramMap = new HashMap<>();
//        //文件
//        paramMap.put("file", file);
//        //输出
//        paramMap.put("output","json");
//        //自定义路径
//        paramMap.put("path","image");
//        //场景
//        paramMap.put("scene","image");
//
//        paramMap.put("filename",zipFileName);

//        String result= HttpUtil.post("http://106.12.241.246:8083/group1/upload", paramMap);
//        String result= HttpUtil.post(fileServerHost+"/group1/upload", paramMap);
//            String result= HttpUtil.post(fileServerHost+"/group1/upload", paramMap);
        FileInputStream input = new FileInputStream(file);
        MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "application/octet-stream", input);
        R<SysFile> result1 = remoteFileService.upload(multipartFile);
        if(result1.getCode() != R.SUCCESS){
            throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
        }
        String url = result1.getData().getHttpsUrl();

        File zipFile = new File(zipFileName);
        if (spOverhaulVo.getType()) {

            if (zipFile.exists()) {
                deleteFolder(folderName);
            }else {
                File excel = new File(folderName + ".xlsx");
                if (excel.exists()) {
                    excel.delete();
                }
            }
        }else{
            File zipFile2 = new File(folderName + ".zip");
            zipFile2.delete();
        }
        if (zipFile.exists()) {
            zipFile.delete();
        }
//        Gson gson = new Gson();
//        JsonObject jsonObject = gson.fromJson(result, JsonObject.class);
        // 获取"url"字段的值
//        String url = jsonObject.get("url").getAsString();
        return url;
    }

    @Override
    public SpOverhaul detail(Long id) {
        SpOverhaul spOverhaul = spOverhaulServiceMapper.getById(String.valueOf(id));
        List<Map<String, String>> list = spOverhaulServiceMapper.getFileIdById(id);

        List<Map<String, String>> updatedList = new ArrayList<>();

        for (Map<String, String> map : list) {
            Map<String, String> updatedMap = new HashMap<>();

            // 复制原有的值
            updatedMap.putAll(map);

            // 转换overhaulId为String类型
            String overhaulIdStr = String.valueOf(map.get("fileId"));
            updatedMap.put("fileId", overhaulIdStr);

            // 提取文件名并添加到map中
            String url = map.get("url");
            if (url != null) {
                int lastSlashIndex = url.lastIndexOf("/");
                if (lastSlashIndex != -1 && lastSlashIndex + 1 < url.length()) {
                    String fileName = url.substring(lastSlashIndex + 1);
                    String decodedFileName = null;
                    try {
                        decodedFileName = URLDecoder.decode(fileName, "UTF-8");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    updatedMap.put("fileName", decodedFileName);
                }
            }

            updatedList.add(updatedMap);
        }

        spOverhaul.setFile(updatedList);

//        Map<String,Object> result = new HashMap<>();
//        result.put("id",spOverhaul.getId());
//        result.put("nameOfVessel",spOverhaul.getNameOfVessel());
//        result.put("imo",spOverhaul.getImo());
//        result.put("inspectionTime",spOverhaul.getInspectionTime());
//        result.put("inspectionContent",spOverhaul.getInspectionContent());
//        result.put("file",spOverhaul.getFile());

        return spOverhaul;
    }

    @Override
    public void updateCon(SpOverhaul spOverhaul) {
        SpOverhaul spOverhaul1 = super.getById(spOverhaul.getId());
        SpOverhaul spOverhaul2 = spOverhaul;
        if (spOverhaul1.getImo() != null && spOverhaul.getImo() != null) {
            if (!spOverhaul.getImo().equals(spOverhaul1.getImo())) {
                spOverhaul2.setNameOfVessel(spOverhaulServiceMapper.getNameByImo(spOverhaul.getImo()));
            }
        }
        if (spOverhaul1.getNameOfVessel()!=null && spOverhaul.getNameOfVessel()!=null){
            if (!spOverhaul.getNameOfVessel().equals(spOverhaul1.getNameOfVessel())){
                spOverhaul2.setImo(spOverhaulServiceMapper.getImoByName(spOverhaul.getNameOfVessel()));
            }
        }
        super.updateById(spOverhaul2);
        String QuaId = String.valueOf(spOverhaul.getId());
        List<String> ids = spOverhaul.getFileIds();
        if(StringUtils.isNotBlank(QuaId)){
            if (CollectionUtil.isNotEmpty(ids)) {
                spFobFileRecordService.getBaseMapper().delete(new LambdaQueryWrapper<SpFobFileRecord>()
                        .eq(SpFobFileRecord::getOverhaulId, QuaId)
                        .eq(SpFobFileRecord::getFileType, "船舶检修")
                        .notIn(SpFobFileRecord::getId, ids));
                List<SpFobFileRecord> fileList = spFobFileRecordService.getBaseMapper().selectList(new LambdaQueryWrapper<SpFobFileRecord>()
                        .eq(SpFobFileRecord::getOverhaulId, QuaId)
                        .eq(SpFobFileRecord::getFileType, "船舶检修"));
                if (CollectionUtil.isNotEmpty(fileList)) {
                    List<Long> fileIdList = fileList.stream().map(SpFobFileRecord::getId).collect(Collectors.toList());
                    ids.forEach(item -> {
                        if (!fileIdList.contains(Long.valueOf(item))) {
                            spFobFileRecordService.getBaseMapper().update(null, new LambdaUpdateWrapper<SpFobFileRecord>()
                                    .eq(SpFobFileRecord::getId, item)
                                    .set(SpFobFileRecord::getOverhaulId, QuaId));
                        }
                    });
                } else {
                    ids.forEach(item -> {
                        spFobFileRecordService.getBaseMapper().update(null, new LambdaUpdateWrapper<SpFobFileRecord>()
                                .eq(SpFobFileRecord::getId, item)
                                .set(SpFobFileRecord::getOverhaulId, QuaId));
                    });
                }
            }else {
                spFobFileRecordService.getBaseMapper().delete(new LambdaUpdateWrapper<SpFobFileRecord>()
                        .eq(SpFobFileRecord::getOverhaulId, QuaId)
                        .eq(SpFobFileRecord::getFileType, "船舶检修"));
            }
        }
//        if (ids != null){
//            for (String id : ids) {
//                spOverhaulServiceMapper.upDateFileId(id,QuaId);
//            }
//        }

    }

    @Override
    public List<Map<String, String>> shipAndImo() {
        List<Map<String, String>> stringStringMap = spOverhaulServiceMapper.getShipAndImo();
        return stringStringMap;
    }

    @Override
    public List<Map<String, String>> nowShipAndImo() {
        List<Map<String, String>> stringStringMap = spOverhaulServiceMapper.getNowShipAndImo();
        return stringStringMap;
    }

    @Override
    public void cancelDelete(String businessKey, Integer staus) {
        if(staus==1){
            this.removeById(businessKey);
        }else if(staus==2){
            SpOverhaul spOverhaul = this.getById(businessKey);
            if(spOverhaul!=null){
                spOverhaul.setDelApply(2);
                this.updateById(spOverhaul);
            }
        }else{
            SpOverhaul spOverhaul = this.getById(businessKey);
            if(spOverhaul!=null){
                spOverhaul.setDelApply(1);
                this.updateById(spOverhaul);
            }
        }
    }

    public static void deleteFolder(String folderName) {
        File folder = new File(folderName);
        deleteFolder(folder);
    }

    private static void deleteFolder(File folder) {
        if (folder.exists() && folder.isDirectory()) {
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteFolder(file);
                    } else {
                        file.delete();
                    }
                }
            }
            folder.delete();
            System.out.println("Folder deleted successfully.");
        } else {
            System.out.println("Folder does not exist or is not a directory.");
        }
    }


    private void zipDirectory(File directory, ZipOutputStream zos, String path) throws IOException {
        File[] files = directory.listFiles();
        byte[] buffer = new byte[1024];

        for (File file : files) {
            if (file.isDirectory()) {
                zipDirectory(file, zos, path + file.getName() + "/");
            } else {
                FileInputStream fis = new FileInputStream(file);
                ZipEntry zipEntry = new ZipEntry(path + file.getName());
                zos.putNextEntry(zipEntry);

                int length;
                while ((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }

                fis.close();
                zos.closeEntry();
            }
        }
    }

    public void zipFile(String fileName) throws IOException {
        // 获取当前目录路径
        String currentDirectory = System.getProperty("user.dir");

        // 创建压缩包文件
        String zipFileName = fileName.substring(0, fileName.lastIndexOf('.')) + ".zip";

        try (FileOutputStream fos = new FileOutputStream(zipFileName);
             ZipOutputStream zos = new ZipOutputStream(fos)) {
            zipFile(new File(currentDirectory + "/" + fileName), "", zos);
        }
    }

    private void zipFile(File fileToZip, String parentPath, ZipOutputStream zos) throws IOException {
        if (fileToZip.isDirectory()) {
            String entryName = parentPath + fileToZip.getName() + "/";
            zos.putNextEntry(new ZipEntry(entryName));
            zos.closeEntry();

            File[] children = fileToZip.listFiles();
            for (File childFile : children) {
                zipFile(childFile, entryName, zos);
            }
        } else {
            FileInputStream fis = new FileInputStream(fileToZip);

            String entryName = parentPath + fileToZip.getName();
            zos.putNextEntry(new ZipEntry(entryName));

            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) >= 0) {
                zos.write(buffer, 0, length);
            }

            fis.close();
            zos.closeEntry();
        }
    }



    public static void exportToExcel(List<SpOverhaul> spOverhaulVos, String filePath) throws IOException {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("SpOverhaul Data");

        Row headerRow = sheet.createRow(0);
        String[] headers = {"船舶名称", "IMO", "检修时间", "检修内容", "备注", "操作时间", "操作人"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
        }

        int rowNum = 1;
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        for (SpOverhaul spOverhaul : spOverhaulVos) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(spOverhaul.getNameOfVessel());
            row.createCell(1).setCellValue(spOverhaul.getImo());
            String formattedDate1 = spOverhaul.getInspectionTime().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime()
                    .format(formatter1);
            row.createCell(2).setCellValue(formattedDate1); // Assuming inspectionTime is a Date object
            row.createCell(3).setCellValue(spOverhaul.getInspectionContent());
            String formattedDate2 = spOverhaul.getCreateDate().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime()
                    .format(formatter2);
            row.createCell(4).setCellValue(spOverhaul.getRemarks());
            row.createCell(5).setCellValue(formattedDate2);
            row.createCell(6).setCellValue(spOverhaul.getCreateBy());

        }

        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
            workbook.write(outputStream);
        }

        workbook.close();
    }

    private boolean isEmptyList(List<?> list) {
        return list == null || list.isEmpty();
    }


//    public void downloadFile(String fileUrl, String destinationFolder) throws IOException {
//        URL url = new URL(fileUrl);
//        URLConnection conn = url.openConnection();
//        InputStream inputStream = conn.getInputStream();
//
//        Path folderPath = Paths.get(destinationFolder);
//        if (!Files.exists(folderPath)) {
//            Files.createDirectories(folderPath);
//        }
//
//        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
//        String filePath = destinationFolder + "/" + fileName;
//
//        FileOutputStream outputStream = new FileOutputStream(filePath);
//
//        byte[] buffer = new byte[1024];
//        int bytesRead;
//        while ((bytesRead = inputStream.read(buffer)) != -1) {
//            outputStream.write(buffer, 0, bytesRead);
//        }
//
//        outputStream.close();
//        inputStream.close();
//
//        System.out.println("文件已下载到目录: " + filePath);
//    }

    public void downloadFile(String fileUrl, String destinationFolder) throws IOException {

        String CsoldPart = "http://10.75.34.224:9300/statics";
        String ZsoldPart = "http://10.75.33.149:9300/statics";
        String CsPart = "https://lngshippingcs.cgp.cnooc/api/file/statics";
        String ZsPart = "https://lngshipping.cgp.cnooc/api/file/statics";

        String newUrl = "";
        if (fileUrl.contains("https://lngshipping.cgp.cnooc")) {
            newUrl = fileUrl.replace(ZsPart, ZsoldPart);
        }else if (fileUrl.contains("https://lngshippingcs.cgp.cnooc")){
            newUrl = fileUrl.replace(CsPart, CsoldPart);
        }else {
            newUrl = fileUrl;
        }

        URL url = new URL(newUrl);
        URLConnection conn = url.openConnection();
        InputStream inputStream = conn.getInputStream();

        Path folderPath = Paths.get(destinationFolder);
        if (!Files.exists(folderPath)) {
            Files.createDirectories(folderPath);
        }

        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        String filePath = destinationFolder + "/" + fileName;

        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
    }
    private static long lastID = System.currentTimeMillis();

    public static long generateSerialVersionUID() {
        return lastID++;
    }
}
